# Process this file with autoconf to generate a configure script

m4_include(acinclude.m4)

# Provide various options to initialize the autoconf and configure processes
AC_PREREQ(2.68) # Require at least autoconf-2.68

AC_INIT([libcyan], [0.0.0], [sayan.chaliha@codegrafix.com], [libcyan], [http://libcyan.googlecode.com/])

AC_REVISION([$68$]) # Revision of configure.ac; increment when changing this file

# Library API version; refer:
# http://www.gnu.org/s/libtool/manual/html_node/Libtool-versioning.html
AC_SUBST([APIVERSION], [0])
AC_SUBST([REVISION], [68])
AC_SUBST([AGE], [$(if test "$(expr ${APIVERSION} - 1)" -lt 0; then expr 0; else expr ${APIVERSION} - 1; fi;)])

AC_COPYRIGHT([® 2011, Sayan Chaliha]) # Copyright info
AC_CONFIG_SRCDIR([configure.ac])      # Top-level source directory
AC_CONFIG_MACRO_DIR([m4])             # Additional m4 macro files directory
AC_CONFIG_AUX_DIR([build-aux])        # Auxiliary build utils directory
AC_PREFIX_DEFAULT([/usr/local])       # Default installation directory

# Display info
AS_BOX([AC_PACKAGE_STRING])

# Checks for build, host, and target triplets
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
AC_CANONICAL_TARGET

# Initialize automake; require at least automake-1.11
AM_INIT_AUTOMAKE([1.11])

# Checks for system features
AC_USE_SYSTEM_EXTENSIONS      # Use system extensions if possible; non-POSIX
AC_SYS_LARGEFILE              # Enable large-file support if required
AC_SYS_LONG_FILE_NAMES        # Check if long file names are supported
AC_SYS_RESTARTABLE_SYSCALLS   # Check for restartable system calls

# Libtool initialization; require at least libtool-2.4.2
LT_PREREQ([2.4.2])
LT_INIT([dlopen win32-dll])

# Checks for C compiler support
AC_PROG_CC            # Probe for C compiler
AC_C_CONST            # Check availability of `const` keyword
AC_C_INLINE           # Check availability of `inline` keyword
AC_C_VOLATILE         # Check availability of `volatile` keyword
AX_C_STATIC           # Check availability of `static` keyword
AX_C_BIGENDIAN_CROSS  # Determine byte order (even when cross-compiling)
AX_C___ATTRIBUTE__    # Check availability of `__attribute__`
AX_C___DECLSPEC       # Check availability of `__declspec`
AX_C___FUNC__         # Check availability of `__func__`
AX_C___FUNCTION__     # Check availability of `__FUNCTION__`
AX_CFLAGS_WARN_ALL    # Enable sufficient level of warning

# Checks for C++ compiler support
AC_PROG_CXX                             # Probe for C++ compiler
AX_CXX_FUNCTION_NONTYPE_PARAMETERS      # Function templates with non-type param
AX_CXX_MEMBER_CONSTANTS                 # Constant integral members
AX_CXX_REINTERPRET_CAST                 # Availability of `reinterpret_cast<>`
AX_CXX_CONST_CAST                       # Availability of `const_cast<>`
AX_CXX_DYNAMIC_CAST                     # Availability of `dynamic_cast<>`
AX_CXX_STATIC_CAST                      # Availability of `static_cast<>`
AX_CXX_IMPLICIT_CAST                    # Availability of C++11 implicit_cast<>
AX_CXX_TEMPLATES                        # Basic templates support
AX_CXX_MEMBER_TEMPLATES                 # Member template support
AX_CXX_MEMBER_TEMPLATES_OUTSIDE_CLASS   # Member template outside class
AX_CXX_PARTIAL_SPECIALIZATION           # Partial specilization of templates
AX_CXX_FULL_SPECIALIZATION_SYNTAX       # Full specilization syntax
AX_CXX_EXPLICIT_INSTANTIATIONS          # Explicit instantiations of templates
AX_CXX_NAMESPACES                       # Namespace support
AX_CXX_MUTABLE                          # Availability of `mutable` keyword
AX_CXX_EXPLICIT                         # Availability of `explicit` keyword
AX_CXX_NAMESPACE_STD                    # Availability of namespace std
AX_CXX_BOOL                             # Checks for internal type `bool`

# Set default language to C++
AC_LANG([C++])
AX_COMPILER_VENDOR

# Extra C++ compiler flags (turn on every damn warning!)
AX_CXXFLAGS_WARN_ALL                    # Enable sufficient level of warning
AX_CXX_CPPFLAGS_STD_LANG                # Preprocessor flags to enable STD-C++
AX_CXX_CXXFLAGS_STD_LANG                # Compiler flags to enable STD-C++
AX_CXX_LDFLAGS_STD_LANG                 # Linker flags to enable STD-C++
AX_CHECK_AND_APPEND_FLAG([-Wmissing-field-initializers])
AX_CHECK_AND_APPEND_FLAG([-Wno-trigraphs])
AX_CHECK_AND_APPEND_FLAG([-Wreturn-type])
AX_CHECK_AND_APPEND_FLAG([-Wnon-virtual-dtor])
AX_CHECK_AND_APPEND_FLAG([-Woverloaded-virtual])
AX_CHECK_AND_APPEND_FLAG([-Wmissing-braces])
AX_CHECK_AND_APPEND_FLAG([-Wparentheses])
AX_CHECK_AND_APPEND_FLAG([-Wswitch])
AX_CHECK_AND_APPEND_FLAG([-Wunused-value])
AX_CHECK_AND_APPEND_FLAG([-Wsign-compare])
AX_CHECK_AND_APPEND_FLAG([-Waddress])
AX_CHECK_AND_APPEND_FLAG([-Wsequence-point])
AX_CHECK_AND_APPEND_FLAG([-Wshorten-64-to-32])
AX_CHECK_AND_APPEND_FLAG([-Wwrite-strings])
AX_CHECK_AND_APPEND_FLAG([-Wold-style-cast])
AX_CHECK_AND_APPEND_FLAG([-arch ${host_cpu}])
AX_CHECK_AND_APPEND_FLAG([-fpch-preprocess])
AS_CASE([${host_cpu}], [*64], [AX_CHECK_AND_APPEND_FLAG([-m64])],
  [AX_CHECK_AND_APPEND_FLAG([-m32])])

# Generated configuration headers
AC_CONFIG_HEADER([lc_config.h])
AC_DEFINE([LC_MAJOR_VERSION], [0], [Major version])
AC_DEFINE([LC_MINOR_VERSION], [0], [Minor version])
AC_DEFINE([LC_UPDATE_VERSION], [0], [Update version])
AC_DEFINE([LC_REVISION], [68], [Revision])
AS_CASE([${ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor}],
  [gnu], [AC_DEFINE([LC_COMPILER_GNU], [1], [define when using GNU G++])],
  [microsoft], [AC_DEFINE([LC_COMPILER_MSVC], [1], [define when using MSVC])])
AX_CREATE_STDINT_H([lc_inttypes.h])
AX_CREATE_TARGET_H([lc_target.h])
AH_TOP([#ifndef _LC_CONFIG_H
#define _LC_CONFIG_H])
AH_BOTTOM(AX_AUTO_INCLUDE_HEADERS([
  cstdlib cstdio cstring cwchar cmath exception stdexcept new cerrno cassert
  cstdarg wctype.h unistd.h fcntl.h aio.h sched.h time.h sys/time.h sys/types.h
  sys/resource.h sys/sysctl.h ioctl.h sys/ioctl.h sys/stat.h Windows.h
  bits/atomicity.h ext/atomicity.h cstddef
]))
AH_BOTTOM([#include "lc_inttypes.h"
#include "lc_target.h"
#endif /* _LC_CONFIG_H */])

# Additional options
## Debug mode
AC_ARG_ENABLE([debug],
  [AS_HELP_STRING([--enable-debug],
    [turn on debugging support @<:@default=no@:>@])],
  [case "${enableval}" in
    yes) enable_debug=true ;;
    no) enable_debug=false ;;
    *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
  esac], [enable_debug=false])
AS_IF([test x"${enable_debug}" = xtrue],
  [AX_CHECK_AND_APPEND_FLAG([-DDEBUG -g3 -ggdb -O0])],
  [AX_CHECK_AND_APPEND_FLAG([-DNDEBUG -O2])])
## Coverage testing
AC_ARG_ENABLE([coverage-testing],
  [AS_HELP_STRING([--enable-coverage-testing],
    [trun on code coverage testing support using gcov @<:@default=no@:>@])],
  [case "${enableval}" in
    yes) enable_coverage_testing=true ;;
    no) enable_coverage_testing=false ;;
    *) AC_MSG_ERROR([bad value ${enableval} for --enable-coverage-testing]) ;;
  esac], [enable_coverage_testing=false])
AS_IF([test x"${enable_coverage_testing}" = xtrue],
  [AX_CHECK_AND_APPEND_FLAG([-fprofile-arcs], [CXXFLAGS])
   AX_CHECK_AND_APPEND_FLAG([-ftest-coverage], [CXXFLAGS])])
AM_CONDITIONAL([TEST_COVERAGE], [test x"${enable_coverage_testing}" = xtrue])
## Optimize for speed
AC_ARG_ENABLE([max-speed],
  [AS_HELP_STRING([--enable-max-speed],
    [turn on maximum optimization for speed @<:@default=no@:>@])],
  [case "${enableval}" in
    yes) enable_max_speed=true ;;
    no) enable_max_speed=false ;;
    *) AC_MSG_ERROR([bad value ${enableval} for --enable-max-speed]) ;;
  esac], [enable_max_speed=false])
AS_IF([test x"${enable_max_speed}" = xtrue],
  [AS_IF([test x"${enable_debug}" = xtrue],
    [AC_MSG_ERROR([cannot optimize in debug mode])],
     [AX_CHECK_AND_APPEND_FLAG([-O3])
      AX_CHECK_AND_APPEND_FLAG([-ffast-math])
      AX_CHECK_AND_APPEND_FLAG([-fkeep-inline-functions])
      AX_CHECK_AND_APPEND_FLAG([-fmerge-all-constants])
      AX_CHECK_AND_APPEND_FLAG([-fmodulo-sched])
      AX_CHECK_AND_APPEND_FLAG([-fgcse-sm])
      AX_CHECK_AND_APPEND_FLAG([-fgcse-las])
      AX_CHECK_AND_APPEND_FLAG([-funsafe-loop-optimizations])
      AC_MSG_WARN([--enable-max-speed also enables optimizations that are not valid for all standards compliant programs])])])
## Exception handling
AC_ARG_ENABLE([exceptions],
  [AS_HELP_STRING([--enable-exceptions],
    [turn on exception handling @<:@default=check@:>@])],
  [case "${enableval}" in
    yes) enable_exceptions=true ;;
    no) enable_exceptions=false ;;
    *) AC_MSG_ERROR([bad value ${enableval} for --enable-exceptions]) ;;
  esac], [enable_exceptions=check])
AS_IF([test x"${enable_exceptions}" = xtrue -o x"${enable_exceptions}" = xcheck], [AX_CXX_EXCEPTIONS])
AS_IF([test x"${enable_exceptions}" = xtrue -a x"${ax_cv_cxx_exceptions}" != xyes],
  [AC_MSG_ERROR([--enable-exceptions specified but no compiler support])],
  [test x"${ax_cv_cxx_exceptions}" != xyes -o x"${enable_exceptions}" = xno],
  [AX_CHECK_AND_APPEND_FLAG([-fno-exceptions])],
  [AX_CHECK_AND_APPEND_FLAG([-fexceptions -DLC_EXCEPTIONS])])

# Checks for libraries and additional packages
## Multithreading API
AC_ARG_WITH([threads],
  [AS_HELP_STRING([[--with-threads[=posix|win32]]],
    [specify multi-threading API @<:@default=check@:>@])],
  [case "${withval}" in
    posix) with_threads=posix ;;
    win32) with_threads=win32 ;;
    yes) with_threads=check ;;
    *) AC_MSG_ERROR([bad value ${withval} for --with-threads]) ;;
  esac], [with_threads=check])
AS_IF([test x"${with_threads}" = xcheck -o x"${with_threads}" = xposix],
    [ACX_PTHREAD],
  [test x"${with_threads}" = xcheck -o x"${with_threads}" = xwin32],
    [dnl ACX_WIN32])
AS_IF([test x"${with_threads}" = xposix -a x"${acx_pthread_ok}" != xyes],
  [AC_MSG_ERROR([--with-threads=posix specified but POSIX threads not found])],
  [test x"${with_threads}" = xwin32 -a x"${acx_win32threads_ok}" != xyes],
  [AC_MSG_ERROR([--with-threads=win32 specified but Win32 threads not found])],
  [test x"${with_threads}" = xcheck],
  [AS_IF([test x"${acx_pthread_ok}" = xyes], [with_threads=posix],
    [AS_IF([test x"${acx_win32threads_ok}" = xyes], [with_threads=win32],
      [AC_MSG_ERROR([no suitable multi-threading API detected])])])])
AM_CONDITIONAL([PTHREAD], [test x"${with_threads}" = xposix])
AM_CONDITIONAL([WINAPI], [test x"${with_threads}" = xwin32])

# Checks for headers
## Standard C++ headers
AC_HEADER_DIRENT
AC_HEADER_STDBOOL
AC_HEADER_TIME
AC_HEADER_STAT
AC_CHECK_HEADERS([cstdlib cstdio cstring cwchar])
AC_CHECK_HEADERS([cmath exception stdexcept new cstdarg])
AC_CHECK_HEADERS([cerrno cassert wctype.h cstddef])
## OS-specific headers
AC_CHECK_HEADERS([fcntl.h aio.h sched.h sys/time.h sys/resource.h])
AC_CHECK_HEADERS([sys/sysctl.h time.h ioctl.h sys/ioctl.h Windows.h])

# Checks compiler characteristics
## Checks for types
AC_TYPE_LONG_LONG_INT
AC_STRUCT_DIRENT_D_INO
AC_STRUCT_DIRENT_D_TYPE
AC_STRUCT_TM
AC_CHECK_MEMBERS([struct stat.st_dev, struct stat.st_atime])
AC_CHECK_MEMBERS([struct stat.st_mtime, struct stat.st_ctime])
AC_CHECK_MEMBERS([struct stat.st_size, struct stat.st_blksize])
AC_CHECK_MEMBERS([struct stat.st_mode, struct stat.st_blocks])
AC_CHECK_MEMBERS([struct _stat.st_dev, struct _stat.st_atime])
AC_CHECK_MEMBERS([struct _stat.st_mtime, struct _stat.st_ctime])
AC_CHECK_MEMBERS([struct _stat.st_size, struct _stat.st_blksize])
AC_CHECK_MEMBERS([struct _stat.st_mode, struct _stat.st_blocks])
LC_CHECK_TYPE_SIZE([size_t])
LC_CHECK_TYPE_SIZE([ssize_t])
LC_CHECK_TYPE_SIZE([int8_t])
LC_CHECK_TYPE_SIZE([int16_t])
LC_CHECK_TYPE_SIZE([int32_t])
LC_CHECK_TYPE_SIZE([int64_t])
LC_CHECK_TYPE_SIZE([uint8_t])
LC_CHECK_TYPE_SIZE([uint16_t])
LC_CHECK_TYPE_SIZE([uint32_t])
LC_CHECK_TYPE_SIZE([uint64_t])
LC_CHECK_TYPE_SIZE([char])
LC_CHECK_TYPE_SIZE([wchar_t])
LC_CHECK_TYPE_SIZE([wint_t])
LC_CHECK_TYPE_SIZE([off_t])
LC_CHECK_TYPE_SIZE([clock_t])
LC_CHECK_TYPE_SIZE([time_t])
LC_CHECK_TYPE_SIZE([ptrdiff_t])

# Checks for library functions
AC_FUNC_LSTAT
AC_FUNC_MALLOC
AC_FUNC_MEMCMP
AC_FUNC_STRERROR_R
AC_FUNC_STRTOD
AC_FUNC_STRTOLD
AC_FUNC_MBRTOWC
AC_FUNC_STRFTIME
AC_FUNC_VPRINTF
AC_FUNC_FORK
AC_FUNC_CHOWN
AC_CHECK_FUNCS([gettimeofday isascii memchr memmove memcpy getenv sysconf])
AC_CHECK_FUNCS([setenv strtol mbstowcs wcstombs pow strerror_s _putenv_s])
AC_CHECK_FUNCS([iswascii _vsnwprintf _open _close _read _write _lchmod _fchmod])
AC_CHECK_FUNCS([_lstat _fstat _lseek _access _dup])
LC_CHECK_GNU_ATOMIC_BUILTINS

# Output files
AC_CONFIG_FILES([
  Makefile
  libcyan.spec
])
AC_OUTPUT
